home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_11_12 / dean / trnsform.c < prev   
C/C++ Source or Header  |  1994-02-03  |  9KB  |  395 lines

  1. /* Listing 2 */
  2.  
  3. /****************************************************/
  4. /*                                                  */
  5. /* Image transformation routines for 320 x 200      */
  6. /* 256 color mode, Borland C                        */
  7. /* Christopher Dean 05/10/93                        */
  8. /*                                                  */
  9. /****************************************************/
  10.  
  11.  
  12. #include <stdio.h>
  13. #include <alloc.h>
  14. #include <math.h>
  15. #include <mem.h>
  16. #include <assert.h>
  17.  
  18. /* direction defines */
  19.  
  20. #define SHEAR_VERT_RIGHT 0
  21. #define SHEAR_VERT_LEFT 1
  22. #define SHEAR_HORZ_RIGHT 1
  23. #define SHEAR_HORZ_LEFT 0
  24.  
  25.  
  26. /* Calculate the Rothstein code given the slope p/q.
  27.    The code is stored in r and is max long */
  28.  
  29. static void Rothstein(char *r,int p,int q,int max)
  30. {
  31.   int i;
  32.   unsigned long psum,qsum;  /* use longs so sums
  33.                    don't overflow */
  34.   int t;
  35.  
  36.   if (p > q) {
  37.  
  38.     /* if slope is greater than 45 degrees
  39.        inverse it */
  40.  
  41.     t = p;
  42.     p = q;
  43.     q = t;
  44.   }
  45.   psum = p;
  46.   qsum = q;
  47.   memset(r,0,max);
  48.  
  49.   /* algrebraically calculate horizontal grid
  50.      intersections as we go from 1 to max */
  51.  
  52.   for (i = 1; i < max; ++i) {
  53.     psum += p;
  54.     if (psum > qsum) {
  55.  
  56.       /* crossed an intersection */
  57.  
  58.       qsum += q;
  59.       r[i] = 1;  /* set code to reflect this */
  60.     }
  61.   }
  62. }
  63.  
  64. /* TransXY - Expand an image to a new height and
  65.    width. It will perform the scaling on the rows
  66.    and columns simultaneously. */
  67.  
  68. /* It allocates and returns the new image */
  69.  
  70.  
  71. char *TransXY(char *source,int width,int height,
  72.        int newwidth,int newheight)
  73. {
  74.   int maxx,maxy,expandx,expandy,i,sourcex,sourcey;
  75.   char *rx,*ry;       /* Rothstein codes */
  76.   char *dest,*dest1;  /* pointers into destination
  77.              image */
  78.   char c;
  79.  
  80.   /* determine if we are shrinking or expanding
  81.      in any directions */
  82.  
  83.   if (newwidth> width) {
  84.     expandx = 1;
  85.     maxx = newwidth;
  86.   }
  87.   else {
  88.     expandx = 0;
  89.     maxx = width;
  90.   }
  91.   if (newheight > height) {
  92.     expandy = 1;
  93.     maxy = newheight;
  94.   }
  95.   else {
  96.     expandy = 0;
  97.     maxy = height;
  98.   }
  99.  
  100.   /* allocate the new image */
  101.  
  102.   dest = (char *) malloc(4+(newwidth * newheight *
  103.       sizeof(char)));
  104.   assert(dest != NULL);
  105.  
  106.   /* set up dimensions in Borland C
  107.      putimage buffer */
  108.  
  109.   *((int *)dest) = newwidth;
  110.   *((int *)dest+1) = newheight;
  111.   dest1 = dest+4;
  112.   source+=4;
  113.  
  114.   /* allocate and calculate Rothstein code
  115.      for both directions */
  116.  
  117.   rx = (char *) malloc(sizeof(char) * maxx);
  118.   ry = (char *) malloc(sizeof(char) * maxy);
  119.   assert(rx != NULL);
  120.   assert(ry != NULL);
  121.   Rothstein(rx,newwidth,width,maxx);
  122.   Rothstein(ry,newheight,height,maxy);
  123.  
  124.   /* always want a 1 as the first in code */
  125.  
  126.   rx[0] = ry[0] = 1;
  127.  
  128.   /* loop through rows of image */
  129.  
  130.   for (sourcey = 0; sourcey < maxy; ++sourcey) {
  131.      if (ry[sourcey] == 1) {
  132.  
  133.     /* just copy the source row.  Loop through
  134.        each column checking to see if that column
  135.        is also suppossed to be copied */
  136.  
  137.     for (sourcex = 0; sourcex < maxx; ++sourcex) {
  138.        if (rx[sourcex] == 1) {
  139.  
  140.           /* copy the pixel in this row and
  141.          column */
  142.  
  143.           *dest1 = *source;
  144.           ++dest1;
  145.           ++source;
  146.        }
  147.  
  148.        else if (expandx) {
  149.  
  150.        /* if expanding duplicate the previous
  151.           pixel, don't increment the source so it
  152.           keeps copying the last column with a 1
  153.           for as many zeros as there are. */
  154.  
  155.           *dest1 = *(dest1-1);
  156.           ++dest1;
  157.        }
  158.        else
  159.  
  160.           /* if shrinking then just skip this
  161.          column */
  162.  
  163.           ++source;
  164.  
  165.  
  166.     }
  167.     }
  168.     else if (expandy) {
  169.  
  170.     /* if expanding duplicate the previous row,
  171.        don't increment the source so it keeps
  172.        copying the last row with a 1 for as many
  173.        zeros as there are. Assumes ry[0] never is
  174.        zero */
  175.  
  176.     memcpy(dest1,dest1-newwidth,newwidth);
  177.     dest1 += newwidth;
  178.     }
  179.     else
  180.  
  181.        /* if shrinking then just skip this row */
  182.  
  183.        source += width;
  184.   }
  185.   free(rx);
  186.   free(ry);
  187.   return(dest);
  188. }
  189.  
  190. /* ShearVert - shear an image to a new height that
  191.    must be greater than the original height.  Passing
  192.    in the new height will give you a shear of
  193.    newheight-height / width thus in some cases it may not
  194.    be possible to get the exact shear you want.  The
  195.    dir parameter specifies whether it is a right shear
  196.    or left shear.  The routine allocates and returns
  197.    the new image.
  198. */
  199.  
  200.  
  201. char *ShearVert(char *source,int width,int height,
  202.    int newheight,int dir)
  203. {
  204.   char *r;
  205.   char *dest,*dest1;
  206.   char c;
  207.   int i,j,k,size,offset,Over45deg,h,adjust;
  208.  
  209.  
  210.   /* new height must be >= old height */
  211.  
  212.   if (newheight < height)
  213.      newheight = height;
  214.  
  215.   /* allocate new image */
  216.  
  217.   size = 4 + (width * newheight * sizeof(char));
  218.   dest = (char *) malloc(size);
  219.   assert(dest != NULL);
  220.  
  221.   /* set background for putting sheared images to
  222.      screen */
  223.  
  224.   memset(dest,255,size);
  225.  
  226.   /* initialize dimensions in Borland C
  227.      putimage buffer */
  228.  
  229.   *((int *)dest) = width;
  230.   *((int *)dest+1) = newheight;
  231.   dest1 = dest+4;
  232.   source+=4;
  233.  
  234.   r = (char *) malloc(sizeof(char) * width);
  235.   assert(r != NULL);
  236.  
  237.   /* calculate Rothstein code and adjust
  238.      for shears greater than 45 degrees */
  239.  
  240.   h = newheight - height;
  241.   Over45deg = h / width;
  242.   Rothstein(r,h-(width*Over45deg),width,width);
  243.  
  244.   /* set dest to start of original image in new
  245.      buffer */
  246.  
  247.   dest1 += (width * h);
  248.   if (dir == SHEAR_VERT_LEFT)
  249.  
  250.      /* for left shears go from left to right
  251.     and move columns up */
  252.  
  253.      adjust = 1;
  254.   else {
  255.  
  256.      /* for right shears go from right to left
  257.     and move columns up */
  258.  
  259.      adjust = -1;
  260.      source += width-1;
  261.      dest1 += width-1;
  262.   }
  263.  
  264.   /* traverse width of original image raising each
  265.      column with a 1 in the Rothstein code up one
  266.      from the previouse level */
  267.  
  268.   for (i = 0; i < width; ++i) {
  269.  
  270.      /* adjust for greater than 45 degrees */
  271.  
  272.      for (k= 0; k < Over45deg; ++k)
  273.  
  274.     /* move the column up one row */
  275.  
  276.     dest1 -= width;
  277.  
  278.      /* check Rothstein code and raise up if 1 */
  279.  
  280.      if (r[i] == 1)
  281.      dest1 -= width;
  282.  
  283.      /* copy the column into new destination
  284.     position */
  285.  
  286.      for (j = 0,offset = 0; j < height; ++j,
  287.           offset += width)
  288.      *(dest1+offset) = *(source + offset);
  289.  
  290.      /* next column */
  291.  
  292.      source += adjust;
  293.      dest1 += adjust;
  294.   }
  295.  
  296.   free(r);
  297.   return(dest);
  298. }
  299.  
  300. /* ShearHorz - shear an image to a new width that must
  301.    be greater than the original width.  Passing in the
  302.    new width will give you a shear of newwidth-width /
  303.    height thus in some cases may not be possible to
  304.    get the exact shear you want.  The dir parameter
  305.    specifies whether it is a right shear or left shear.
  306.    The routine allocates and returns the new image.
  307. */
  308.  
  309.  
  310. char *ShearHorz(char *source,int width,int height,
  311.      int newwidth,int dir)
  312. {
  313.   char *r;
  314.   char *dest,*dest1;
  315.   char c;
  316.   int i,j,k,size,Over45deg,w,adjust,offset;
  317.  
  318.   /* make sure new width > old width */
  319.  
  320.   if (newwidth < width)
  321.      newwidth = width;
  322.  
  323.   /* allocate and initialize new image */
  324.  
  325.   size = 4 + (newwidth * height * sizeof(char));
  326.   dest = (char *) malloc(size);
  327.   assert(dest != NULL);
  328.   memset(dest,255,size);
  329.   *((int *)dest) = newwidth;
  330.   *((int *)dest+1) = height;
  331.   dest1 = dest+4;
  332.   source+=4;
  333.  
  334.   if (dir == SHEAR_HORZ_RIGHT)
  335.  
  336.      /* for right shears go from left
  337.     to right moving the rows over */
  338.  
  339.      adjust = 1;
  340.  
  341.   else {
  342.  
  343.      /* for left shears go from right
  344.     to left moving the rows over */
  345.  
  346.      adjust = -1;
  347.      source += width-1;
  348.      dest1 += newwidth-1;
  349.   }
  350.   r = (char *) malloc(sizeof(char) * height);
  351.   assert(r != NULL);
  352.  
  353.   /* adjust for shears greater than 45 degrees
  354.      and calculate Rothstein code */
  355.  
  356.   w = newwidth - width;
  357.   Over45deg = w / height;
  358.   Rothstein(r,w-(height*Over45deg),height,height);
  359.  
  360.   /* traverse height of image moving each
  361.      row with a 1 in the Rothstein code over
  362.      one from the previous width */
  363.  
  364.   for (i = 0; i < height; ++i) {
  365.  
  366.      /* adjust f